#include <rc_gpio/c_gpio.h>
#include <boost/format.hpp>
#include <fcntl.h>
#include <iostream>
#include <string>
#include <boost/thread/mutex.hpp>
#include <boost/thread/pthread/mutex.hpp>

#define SYSFS_GPIO_EXPORT            "/sys/class/gpio/export"
#define SYSFS_GPIO_UNEXPORT          "/sys/class/gpio/unexport"
#define SYSFS_GPIO_RST_DIR           "/sys/class/gpio/gpio%d/direction"
#define SYSFS_GPIO_RST_VAL           "/sys/class/gpio/gpio%d/value"
#define SYSFS_GPIO_RST_DIR_VAL_OUT   "out"
#define SYSFS_GPIO_RST_DIR_VAL_IN    "in"
#define SYSFS_GPIO_RST_VAL_H        "1"
#define SYSFS_GPIO_RST_VAL_L        "0"
namespace RC {
    namespace GPIO {
        boost::mutex gpio_mutes;
        void pinMode(int gpio, int direction) {
            pinFree(gpio);
            boost::mutex::scoped_lock lock(gpio_mutes);
            int fd;
            //打开端口/sys/class/gpio# echo gpio > export
            fd = open(SYSFS_GPIO_EXPORT, O_WRONLY);
            if (fd == -1) {
                return;
            }
            std::string export_gpio=std::to_string(gpio);
            write(fd, export_gpio.c_str(), export_gpio.size());
            close(fd);

            //设置端口方向/sys/class/gpio/gpio%d# echo out > direction
            boost::format fmt(SYSFS_GPIO_RST_DIR);
            fmt % gpio;
            std::string targetString = fmt.str();
            fd = open(targetString.c_str(), O_WRONLY);
            if (fd == -1) {
                return;
            }
            if (direction == RC_GPIO_INPUT) {
//                std::cout<<targetString<<" Dist:"<<SYSFS_GPIO_RST_DIR_VAL_IN<<std::endl;
                write(fd, SYSFS_GPIO_RST_DIR_VAL_IN, sizeof(SYSFS_GPIO_RST_DIR_VAL_IN));
            } else {
//                std::cout<<targetString<<" Dist:"<<SYSFS_GPIO_RST_DIR_VAL_OUT<<std::endl;
                write(fd, SYSFS_GPIO_RST_DIR_VAL_OUT, sizeof(SYSFS_GPIO_RST_DIR_VAL_OUT));
            }
            close(fd);
        }

        void digitalWrite(int gpio, int value) {
            //设置端口数值/sys/class/gpio/gpio%d/value# echo value > value
            boost::mutex::scoped_lock lock(gpio_mutes);
            boost::format fmt(SYSFS_GPIO_RST_VAL);
            fmt % gpio;
            std::string targetString = fmt.str();
            int fd = open(targetString.c_str(), O_WRONLY);
            if (fd == -1) {
                return;
            }
            if (value == RC_GPIO_HIGH) {
//                std::cout<<targetString<<" Value:"<<SYSFS_GPIO_RST_VAL_H<<std::endl;
                write(fd, SYSFS_GPIO_RST_VAL_H, sizeof(SYSFS_GPIO_RST_VAL_H));
            } else {
//                std::cout<<targetString<<" Value:"<<SYSFS_GPIO_RST_VAL_L<<std::endl;
                write(fd, SYSFS_GPIO_RST_VAL_L, sizeof(SYSFS_GPIO_RST_VAL_L));
            }
            close(fd);
        }

        void pinFree(int gpio) {
            boost::mutex::scoped_lock lock(gpio_mutes);
            //打开端口/sys/class/gpio# echo gpio > export
            int fd = open(SYSFS_GPIO_UNEXPORT, O_WRONLY);
            if (fd == -1) {
                return;
            }

            std::string export_gpio = std::to_string(gpio);
            write(fd, export_gpio.c_str(), export_gpio.size());
            close(fd);
        }
    }
}